import Core from 'crypto-js/core'
import SHA256 from 'crypto-js/sha256'
import Hex from 'crypto-js/enc-hex'
import WordArray from 'crypto-js/lib-typedarrays'

Core.SHA256 = SHA256

/**
 * 计算文件 hash
 * @param file 文件
 * @param type SHA256, MD5, SHA1 等
 * @param onUpdate
 * @param onError
 * @return {Promise<string>}
 */
export const computeFileHash = (file, { type = 'SHA256', onUpdate, onError }) => {
  const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
  const fileReader = new FileReader()
  const algorithm = Core.algo[type].create()
  let currentChunk = 0
  const chunkSize = 10 * 1024 * 1000
  const totalChunk = Math.ceil(file.size / chunkSize)
  const readChunk = () => {
    const start = currentChunk * chunkSize
    const end = start + chunkSize >= file.size ? file.size : start + chunkSize
    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
  }

  return new Promise((resolve, reject) => {
    fileReader.onerror = e => {
      onError?.(e)
    }
    fileReader.onload = ({ target }) => {
      onUpdate?.(currentChunk, totalChunk)
      algorithm.update(WordArray.create(target.result))
      if (currentChunk < totalChunk) {
        if (file.canceled) {
          algorithm.reset()
          reject(Error('canceled'))
          return
        }
        currentChunk++
        readChunk()
      } else {
        const hash = algorithm.finalize().toString(Hex)
        algorithm.reset()
        resolve(hash)
      }
    }
    readChunk()
  })
}
